Meeting the additional documentation requirements
*************************************************

The ANS defines a large number of details to be implementation defined or ambiguous. An ANS-Forth System has to document it's behavior in these situations if possible.

The Core Words
==============

Implementation Defined Options
------------------------------

alignment of data:
     To access memory cells with @ and ! pfe utilizes the C assignment operator. In general this means that a word size transfer instruction is generated. On many CPUs such a transfer instruction can only access aligned data. In most cases on such a CPU a misaligned access causes a SIGBUS signal to be sent to the pfe process. pfe maps this signal to an address alignment exception, THROW-code -23.

EMIT and non-graphic characters:
     See Display output.

character editing of ACCEPT and EXPECT:
     See Keyboard input.

character set:
     pfe uses the character set of your computer. pfe is 8-bit-clean, i.e. you can use characters with codes above 127 wherever you like. What characters >127 are defined depends on your equipment. However in Unix-environments quite often a part of the communication channel to the computer running pfe strips the eights bit (e.g. the telnet-program).

Character-aligned address requirements:
     pfe uses the C data type unsigned char to represent characters stored in memory. ANSI-C requires there are no alignment restrictions to that type.

character-set extensions and matching of names:
     You can use any 8-bit non-control character in names. When lower case input is disabled, an entered name must match a name in the dictionary exactly. When lower case input is enabled and your system uses the ISO 8895-1 (a/k/a latin-1) character set (an extension of the ASCII) then lower case international characters are matched correctly. Same applies to the IBM-PC OEM character set. Take care when porting to machines with other character sets.

conditions under which control characters match a space delimiter:
     When WORD or PARSE are called with space as a delimiter then any character that makes the C-macro isspace() true is accepted as delimiter. This means that a blank as delimiter swallows line ends and tabs too.

format of the control flow stack:
     The data stack is used as control flow stack. Two cells represent one item: the lower cell is an address, the upper cell is a magic number encoding the type of control structure this item belongs to. Magic numbers for each type are defined as constants:

     DEST_MAGIC
          The address can be used as destination of a jump.

     ORIG_MAGIC
          The address is a source address, destination of jump has yet to be stored in there. See AHEAD.

     LOOP_MAGIC
          The address is a source address and the source is a DO or ?DO-statement.

     CASE_MAGIC
          The address is a source address and the source is an ENDOF.

     OF_MAGIC
          The address is a source address and the source is an OF.

conversion of digits > 35
     When BASE is large enough and LOWER-CASE is false, then digits > 35 are mapped to the lower case characters a through z. If LOWER-CASE is true, then pfe makes no difference between lower and upper case letters and digits > 35 are not available.

display after input terminates in ACCEPT and EXCEPT:
     The cursor is moved to the end of the entered string, then one space is issued, no newline. (May change when pfe runs under control of emacs.)

exception abort sequence of ABORT":
     Issues the error message along with information about the input source where the error occurred. Then does a -2 THROW.

input line terminator:
     Lines typed interactively or read from an INCLUDED file are terminated by the \n character as the C-languages defines it. This is either of CR (^M) or LF (^J) or both.  If your terminal has a special Enter-key that issues something else than CR or LF then this special Enter-key too terminates a command line.

maximum size of a counted string:
     Depends on your memory.

maximum size of a parsed string:
     Depends on your memory.

maximum size of a definition name, in characters:
     31

maximum string length for ENVIRONMENT?, in characters:
     31

method of selecting the user input device:
     The user input device is the standard input of the C-stdio-library. Normally pfe uses unbuffered input on a character by character base.

     On many systems the input can be redirected to come from a file by means of the shell-commandline, i.e. outside pfe. When pfe detects such a redirection it uses buffered stream input instead.

method of selecting the user output device:
     The user output device is the standard output of the C-stdio-library. The C library's buffers are flushed after every single EMIT and TYPE.

     On many systems output can be redirected to a file or printer by means of the shell-commandline, i.e. outside pfe. When pfe detects such a redirection it uses buffered output instead of flushing after every output command.

methods of dictionary compilation:
     See Dictionary structure

number of bits in one address unit:
     Depends on the machine. On most systems: 32, no reports about 16 bit ports so far. Maybe 64. Use ENVIRONMENT? to determine.

number representation and arithmetic:
     pfe uses the integer data types provided by the C-language. Not tested with machines using other representations than binary and the two's-complement for negative numbers.

ranges for integer types:
     Depend on the machine. Use ENVIRONMENT? to determine.

read-only data space regions:
     All data structures pfe defines (dictionary, block and line buffers, PAD etc.) are entirely located in writable RAM. There are no other system parts logically visible to the Forth user. However the address space is typically larger than the dictionary and surely there exist things like C's code, data and stack areas not to mention the address spaces of other programs.

     If these areas are writable and if it makes sense to write there, depends on the hardware and operating system. In unix-like systems they mostly aren't and it doesn't so you better shouldn't try.

size of buffer at WORD:
     The buffer utilized by WORD is the address returned by HERE or DP @. There is room for a string of length 255 but this room is shared with the buffer for pictured numeric output growing down from the upper end of the buffer. This upper end is the address returned by PAD.

size of one cell in address units:
     Depends on the machine. On most systems using 32 Bit cells: 4. On a 64 bit system it would be 8. On a 16 bit system it would be 2. Use 1 CELLS . to determine.

size of one character in address units:
     1.

size of the keyboard terminal buffer:
     256 characters.

size of the pictured numeric output buffer:
     255 characters growing towards lower addresses starting at the character below PAD which is just HERE 256 +. This buffer is shared with WORD which uses the lower end.

size of the scratch area returned by PAD:
     Depends on the free room in the dictionary. Dictionary overflow happens when there are less than 1024 address units left above PAD, so you can rely on 1024.

system case-sensitivity characteristics:
     Dictionary searches are case sensitive and all predefined words are upper case. However you can enter Forth-Code in lower case when the variable LOWER-CASE contains a non-zero value. Then all input is converted to upper case. If LOWER-CASE contains 0, then case is preserved as entered.

     Caution: When LOWER-CASE is true, you can only access upper case definitions. You can define words containing lower case letters only when the variable LOWER-CASE is set false. When lateron LOWER-CASE is true then you can't access these definitions any more.

system prompt:
     QUIT doesn't prompt for a command line. Having executed a command line QUIT issues the characters ok and a newline.

division rounding:
     /MOD is equivalent to FM/MOD, /MOD, /, MOD, */, */MOD all round the quotient towards negative infinity. This is also known as floored divide.

values of STATE when true:
     When compiling the value of STATE is -1 else 0.

values returned after arithmetic overflow:
     Depend on the system and the C-compiler. Most configurations do addition, subtraction and multiplication silently modulo 2**bits-per-cell. Most systems generate an exception when division by 0 is tried but not when divide overflow occurs.

     The integer-divide-by-zero exception is on unix-like systems indistinguishable from a floating point error and reported as such.

whether the current definition can be found after DOES>:
     No.

Ambiguous conditions
--------------------

a name is neither a word nor a number:
     Causes -13 THROW which unless caught issues the message "undefined word" and aborts.

a definition name exceeds the maximum length allowed:
     Causes -19 THROW which unless caught issues the message "definition name too long" and aborts.

addressing a region not inside the various data spaces of the forth system:
     Result depends on the hardware and operating system but hopefully causes an SIGSEGV exception that leads to -9 THROW which unless caught issues the message "invalid memory address" and aborts.

argument type incompatible with parameter:
     Some cases of this error cause -12 THROW which unless caught issues the message "argument type mismatch" and aborts.

attempting to obtain the execution token of a word with undefined execution semantics:
     You get an execution token representing the compilation semantics instead. Executing this execution token while in interpreting state causes -14 THROW which unless caught issues the message "interpreting a compile-only word" and aborts.

dividing by zero:
     Result depends on the hardware and the operating system. On many unix-like systems this raises a SIGFPE leading to -55 THROW which unless caught issues the message "floating point unidentified fault" and aborts.

insufficient data stack or return stack space:
     When detected this leads to -5 THROW or -6 THROW respectively which unless caught issue the message "[return] stack overflow" and abort. Checks for overflow take place after a command line was executed by QUIT or if you execute the word ?STACK.

insufficient space for loop control parameters:
     Will never be detected.

insufficient space in the dictionary:
     Causes -8 THROW which unless caught issues the message "dictionary overflow" and aborts. Chances to detect this in time are good.

interpreting a word with undefined interpretation semantics:
     Causes -14 THROW which unless caught issues the message "interpreting a compile-only word" and aborts.

modifying the contents of the input buffer or a string literal:
     These are located in writable memory and can be modified. Modifying the input buffer and re-interpreting the changed stuff by manipulating >IN is possible.

overflow of the pictured numeric output string:
     Causes -17 THROW which unless caught issues the message "pictured numeric output string overflow" and aborts.

parsed string overflow:
     PARSE (-- addr +n) cannot overflow while WORD stores a counted string in HERE and is limited to 255 characters. If the string WORD has to store exceeds 255 characters a -18 THROW is raised which unless caught issues the message "parsed string overflow" and aborts.

producing a result out of range:
     Results depend on the system. Many systems silently do arithmetic modulo 2**bits-per-cell. If a system raises a signal in such a situation this signal will hopefully lead to the appropriate THROW. Check for unusual signals available on your system when porting pfe.

reading from an empty data or return stack:
     When determined causes -3 THROW or -4 THROW respectively which unless caught issue the message "[return] stack underflow" and abort. Checks take place after a commandline was interpreted by QUIT or when the word ?STACK is executed.

unexepected end of the input buffer, resulting in an attempt to use a zero-length string as a name:
     Causes -16 THROW which when not caught issues the message "attempt to use a zero-length string as a name" and aborts.

>IN greater than input buffer:
     Next call of WORD or PARSE returns a zero length string.

RECURSE appears after DOES>:
     Compiles a recursive call to the defining word not to the defined word.

argument input source different than current input source for RESTORE-INPUT:
     If the argument input source is a valid input source then it gets restored. Otherwise causes -12 THROW which unless caught issues the message "argument type mismatch" and aborts.

data space containing definitions gets de-allocated:
     The dictionary structure becomes corrupted. The system may continue to work for some time but will sooner or later report unexepected "invalid memory address" errors.

data space read/write with incorrect alignment:
     Result depends on the hardware and the operating system. If the hardware raises a SIGBUS in such a case this leads to a -23 THROW which unless caught issues the message "address alignment exception" and aborts.

data space pointer not properly aligned, ,, C,:
     You can always savely C,, for , see above: read/write with incorrect alignment.

less than u+2 stack items (PICK and ROLL):
     This error is not detected as such. PICK and ROLL happily access memory beyond (i.e. above) the bottom of the stack. Unless u is very large this doesn't cause an exception since the region above the data stack is the return stack which belongs to the writable address space of pfe.

loop control parameters not available:
     LOOP or +LOOP can't be compiled without their matching DO or ?DO. Trying to do so results in -22 THROW which unless caught issues the message "control structure mismatch" and aborts.

     However I, J, LEAVE and UNLOOP can be compiled without enclosing loops. When executing the resulting word I and J return garbage while LEAVE and UNLOOP will most likely cause a sort of memory fault, i.e. abort.

most recent definition does not have a name (IMMEDIATE):
     Well, IMMEDIATE flags the most recent definition immediate that does have a name.

name not defined by VALUE used by TO:
     Causes -32 THROW which unless caught issues the message "invalid name argument" and aborts.

name not found (', POSTPONE, ['], [COMPILE]:
     causes -13 THROW which unless caught issues the message "undefined word" and aborts.

parameters are not of the same type:
     Assume single precision integer numbers.

     WITHIN works for both signed and unsigned numbers but fails if lower and upper bound are meant to be of different types and the difference between them is greater than 2**wordbits-1. No error is detected.

     DO can loop at most loop 2**bits-per-word times, and ?DO can loop at most loop (2**bits_per_word - 1) times. Thus if the bounds are meant to be of different type and their difference exceeds this maximum, the loop is executed only (upper bound - lower bound) - 2**bits_per_word times. No error is detected.

POSTPONE or [COMPILE] applied to TO:
     Assume : X POSTPONE TO ; IMMEDIATE

     Now X is equivalent to TO. When later X gets executed in compile mode, the compilation semantics of TO will be executed. If X gets executed in interpretive state, the execution semantics of TO will be executed.

String longer than a counted string returned by WORD:
     This cannot happen, since in case a string in the input is too long WORD throws a -18, "parsed string overflow".

u greater than or equal to the number of bits in a cell (LSHIFT, RSHIFT:
     The result depends on the CPU running pfe and the C-compiler used to build it. Some systems take the shift count modulo the bits in the cell. In these systems a 32 LSHIFT (on a 32 bit machine) is a no-op.

     Other systems return 0 after shifting out all significant bits.

word not defined via CREATE:
     doing a >BODY is harmless since it simply adds an offset to the address on the stack.

     DOES> always applies to the last defined word and changes this words execution semantics to perform everything between DOES> and ; with the data field address of the definition on the stack. Dirty tricks like self-defining words work as expected.

words improperly used outside <# and #>:
     The words in question perform their execution semantics. No error is reported.

Other system documentation
--------------------------

nonstandard words using PAD:
     file manipulation words that temporaily store a file name in PAD are: $CWD, PWD, MV, CP and LN.

operator's terminal facilities available:
     See Controlling keyboard and display

program data space available:
     depends on command line options or on configurable defaults when building pfe. Use .MEMORY to display.

program data space available:
     depends on command line options or on configurable defaults when building pfe. Use .MEMORY to display.

return stack space available:
     depends on command line options or on configurable defaults when building pfe. Use .MEMORY to display.

stack space available:
     depends on command line options or on configurable defaults when building pfe. Use .MEMORY to display.

system dictionary space required, in address units:
     about 20000. Use .MEMORY to display the used dictionary space just after startup. Add a few KBytes that are needed for PAD.

The optional Block word set
===========================

Implementation Defined Options
------------------------------

the format for display by LIST:
     16 numbered lines with 64 characters each. -TRAILING is applied to each line before displaying and one space is displayed afterwards. Thus the text is displayed with exacly one trailing space per line.

the length of a line affected by \:
     64 characters.

Ambiguous conditions
--------------------

correct block read was not possible:
     Result depends on the cause of the problem: A file error is reported using the C-libraries strerror()-message (see below). An invalid block number is reported as such. If no block file is active then this fact is reported.

I/O exception in block transfer:
     The C-library specifies I/O problems in the errno C-variable. pfe maps this error conditon to a THROW with a code calculated as: -256 - errno. If this exception isn't caught it leads to a message strerror (errno) (i.e. the appropriate system error message) and aborts.

invalid block number:
     causes -35 THROW which unless caught issues the message "invalid block number" and aborts.

a program directly alters the contents of BLK:
     SOURCE, WORD and PARSE are sensitive to the contents of BLK in every single call. This means that if a program changes BLK the other block becomes the active input source immediately without resetting >IN to 0.

no current block buffer for UPDATE:
     causes -35 THROW which unless caught issues the message "invalid block number" and aborts.

Other system documentation
--------------------------

any restrictions a multiprogramming system places on the use of buffer addresses:
     N/A.

the number of blocks available for source and data:
     depends on your disk space.

The optional Double Number word set
===================================

Implementation Defined Options
------------------------------

No additional documentation requirements.

Ambiguous conditions
--------------------

d outside of range on n in D>S:
     pfe simply discards the most significant bits. When they contained significant digits then this is overflow situation, the result is wrong, no error is reported.

Other system documentation
--------------------------

No additional documentation requirements.

The optional Exception word set
===============================

Implementation Defined Options
------------------------------

THROW-codes used in the system:

       * -257 through -256 - (largest errno): file errors.

       * -2048: no or not matching binary image.

       * -2049: binary image too big.

       * -2050: out of memory.

       * -2051: array index out of range in ACCESS-ARRAY.

Ambiguous conditions
--------------------

No additional documentation requirements.

Other system documentation
--------------------------

No additional documentation requirements.

The optional Facility word set
==============================

Implementation Defined Options
------------------------------

encoding of keyboard events (EKEY):
     See EKEY-codes.

duration of a system clock tick and repeatability of MS:
     depends largely on your system (respectively the port of pfe to your system), and the system load. On most modern unices pfe utilizes the poll() or select() function to delay it's execution. These functions expect their arguments in micro-seconds. On DOS and OS/2 pfe uses a call to the EMX-library that delays execution with a resolution of milli-seconds. When your port is bad, pfe resorts to the sleep() function which works only for entire seconds.

Ambiguous conditions
--------------------

AT-XY can't be performed on user output device:
     Largely terminal dependant. No range checks are done on the arguments. No errors are reported. You may see some garbage appearing, you may see simply nothing happen.

Other system documentation
--------------------------

No additional documentation requirements.

The optional File-Access word set
=================================

Implementation Defined Options
------------------------------

File access methods used:
     pfe uses the standard C library to access files. ANSI-C has no notion of users and groups but only of read and write access to files. On unix-like systems this means that your umask-setting determines the file access permission of created files. The forth file access modes are not file permissions.

     The fileid data type is a pointer to an internal data structure where pfe keeps the file name, a buffer in case the file is used as block file and C's FILE* to access the file.

     When opening or creating a file, pfe uses the C-library function fopen() with the following strings to specify the access mode:

     CREATE-FILE
          opens a file with fopen() called with the following mode strings:

          R/O
               uses first mode string "w" to create or truncate the file then closes it and opens it again with mode string "r". Pretty useless since it gives you a file for read-only access that is empty.

          W/O
               uses mode string "w" to create or truncate the file. Returned file-id denotes an empty file that is open for write-only access.

          R/W
               uses mode string "w+" to create or truncate the file. Returned file-id denotes an empty file that is open for write and read access.

     OPEN-FILE
          opens a file with fopen() called with the following mode strings:

          R/O
               "r", returned file-id denotes a file open for read-only access.

          W/O
               "r+", the returned file-id denotes a file open for write access only. However it's just pfe prohibiting you from writing to that file. Because in ANSI-C there is no other way to open a file for writing without truncating it from C's point of view this file is open for read and write access. On unix-like systems this means that you must have read permissions too on a file you open with W/O.

          R/W
               "r+", returned file-id denotes a file you can read and write to.

     BIN
          When the file mode is supplemented by the word BIN this adds a "b" for ``binary'' to all fopen() mode strings above.

file exceptions:

     RESIZE-FILE
          raises -37 THROW when called with a file-id of 0 or when the file-id denotes a file that isn't open.

file line terminator:
     pfe uses the same line terminator as the C-language: '\n'. On unix-like systems this is usually ASCII 10, line feed, on DOS and OS/2 it is usually ASCII 13 and ASCII 10, carriage return and line feed.

file name format
     depends on the operating system. On unix-like system use / to form path names from directories and file name, on DOS and OS/2 use \.

information returned by FILE-STATUS:
     FILE-STATUS returns the best possible file access mode for the given file name: Either R/O, W/O or R/W. BIN is assumed to be applicable along with the retured mode. FILE-STATUS reports a file permission.

input file state after an exception when including source:
     Files opened by nested includes are closed. If the exception was caught in a file then only files included from that file are closed. If the exception wasn't caught then ABORT issues an error message, then calls QUIT and QUIT before accepting input from a command line closes all open files.

ior values and meaning:
     When a file error occurred pfe return the value of the errno Variable in the C runtime environment. How many different values are reported this way and what these values mean depends on your operating system. ior is 0 or positive. You can throw an exception if it is positive like this: -256 SWAP - THROW to abort with an appropriate message. To the same end you can call ?FILE ( ior --- ) which doesn't abort if ior is zero.

maximum depth of file input nesting:
     pfe keeps all files INCLUDED open, thus this is limited to the number of simultaneously open files. This is limited by the operating system but also by pfe which uses one of a limited number of internal data structures to keep information about open files. How many depends on command line options when starting pfe or on configurable defaults when building pfe, typically 16.

maximum size of input line:
     1024

methods of mapping block ranges to files:
     No mapping of block ranges across multiple files takes place. A block file is opened with the "b" binary mode specification to fopen(). Inside a block file a block commences at every file position evenly divisible by the block size 1024. No other data but just one block after the other is stored in the file.

number of string buffers provided by S":
     1

size of string buffer used by S":
     255

Ambiguous conditions
--------------------

attempting to position a file outside it's boundaries:
     Results depend on the operating system. With DOS and unix-like systems you can write behind the end of the file. If you do so then DOS fills the space with garbage that happens to be on the disk in the gap and unix only allocates the blocks written.

attempting to read from file positions not yet written:
     On unix-like systems reading behind the end of file is an end-of-file condition, i.e. it returns 0 bytes read and ior 0, no error.

Other system documentation
--------------------------

Implementation Defined Options
------------------------------

Ambiguous conditions
--------------------

Other system documentation
--------------------------

Implementation Defined Options
------------------------------

Ambiguous conditions
--------------------

Other system documentation
--------------------------

Implementation Defined Options
------------------------------

Ambiguous conditions
--------------------

Other system documentation
--------------------------

Implementation Defined Options
------------------------------

Ambiguous conditions
--------------------

Other system documentation
--------------------------

Implementation Defined Options
------------------------------

Ambiguous conditions
--------------------

Other system documentation
--------------------------

Implementation Defined Options
------------------------------

Ambiguous conditions
--------------------

Other system documentation
--------------------------